package tables

import (
	"fmt"
	"path/filepath"
	"server/application/db/schema/dbops"
	"server/application/db/schema/sdto"
	"server/application/db/schema/sentity"
	"server/application/dto"
	"server/application/dto/requestdto"
	"strings"

	"server/pkg/filehelper"
	"server/pkg/myexcel"
	"server/pkg/mylog"
	"server/pkg/where"
	"time"

	"server/application/db/schema/keys"
	"server/application/db/schema/scols"

	"gorm.io/gorm"
)

type DbSvcUserAccount struct {
	dbWrite *gorm.DB
	dbRead  *gorm.DB
}

func NewUserAccount(dbWrite_, dbRead_ *gorm.DB) *DbSvcUserAccount {
	return &DbSvcUserAccount{
		dbWrite: dbWrite_,
		dbRead:  dbRead_,
	}
}

// Create 创建数据
func (s *DbSvcUserAccount) Create(dtoCreate *sentity.UserAccount) (*sentity.UserAccount, error) {
	err := dbops.CreateNew(dtoCreate, s.dbWrite)
	if dtoCreate == nil || dtoCreate.ID <= 0 {
		return nil, fmt.Errorf("创建失败，info数据为空")
	}

	return dtoCreate, err
}

// 根据华为的openid创建或更新用户
func (s *DbSvcUserAccount) CreateOrUpdateUser(param *requestdto.UserAccountLoginHuawei, unionId string) (*sentity.UserAccount, error) {
	wheres := where.FormatOne(scols.UserAccountHuaweiOpenid, "=", param.OpenID)
	total, _ := s.GetTotal(wheres)
	param.AvatarUri = s.HandleUserAvatar(param.AvatarUri, param.OpenID)
	if total == 0 { //没有则创建
		createRes, err := UserAccount.Create(&sentity.UserAccount{
			HuaweiUnionID: unionId,
			HuaweiOpenid:  param.OpenID,
			Username:      param.NickName,
			Avatar:        param.AvatarUri,
		})
		if err != nil {
			return nil, err
		}
		if createRes.ID == 0 {
			return nil, fmt.Errorf("创建用户失败")
		}

		return createRes, nil
	} else { //有则更新头像信息
		updateCols := []string{
			scols.UserAccountAvatar,   //头像暂时不更新头像
			scols.UserAccountUsername, //昵称
		}
		UserAccount.Update(wheres, &sentity.UserAccount{
			WechatOpenId: unionId,
			Username:     param.NickName,
			Avatar:       param.AvatarUri,
		}, updateCols...)

	}
	return UserAccount.FindOne(where.FormatOne(scols.UserAccountHuaweiOpenid, "=", param.OpenID))
}

// 处理用户头像
func (s *DbSvcUserAccount) HandleUserAvatar(avatatr string, huawei_openid string) string {
	defaultAvatar := filepath.Join("static/images/avatar/default.png")
	if avatatr == "" {
		avatatr = defaultAvatar
	}
	//如果是远程图像则先使用远程图像
	if strings.Contains(avatatr, "https://") || strings.Contains(avatatr, "http://") {
		//获取一个uuid
		fileName := fmt.Sprintf("%v.png", huawei_openid)
		//当前日期
		// date := time.Now().Format("20060102")
		savePath := filepath.Join("static/images/avatar", fileName)
		createDirRes := filehelper.CreateDir(savePath)
		println(createDirRes)
		err := filehelper.DownloadImage(avatatr, savePath)
		if err != nil {
			mylog.Error("下载头像失败,error:" + err.Error())
		}
		if !filehelper.FileExists(savePath) { //使用默认头像
			avatatr = defaultAvatar
			mylog.Error("下载头像失败，使用默认头像")
		} else {
			avatatr = savePath
		}
	} else {
		avatatr = defaultAvatar
	}
	return avatatr
}

// FindOne 查询一条数据
func (s *DbSvcUserAccount) FindOne(wheres []*where.Condition) (*sentity.UserAccount, error) {
	entityInfo := new(sentity.UserAccount)
	err := dbops.FindOneNew(&dbops.FindOneConfig{
		Wheres:    wheres,
		Db:        s.dbRead,
		NewEntity: entityInfo,
	})
	if err != nil {
		return nil, err
	}
	if entityInfo == nil || entityInfo.ID <= 0 {
		return nil, fmt.Errorf("查询到的数据为空")
	}

	return entityInfo, nil
}

// 软注销用户
func (s *DbSvcUserAccount) Cancel(uid uint) error {
	wheres := where.FormatOne("id", "=", uid)
	entityInfo, err := s.FindOne(wheres)
	if err != nil {
		return err
	}
	per := fmt.Sprintf("%v_%v", keys.PreCancel, time.Now().Format("20060102150405"))
	//注销用户
	updatedata := sentity.UserAccount{
		IsCancel:      true,
		HuaweiOpenid:  per + entityInfo.HuaweiOpenid,
		HuaweiUnionID: keys.PreCancel + "",
		WechatOpenId:  per + entityInfo.WechatOpenId,
		MiniAppOpenId: keys.PreCancel + "",
	}

	updateCols := []string{scols.UserAccountIsCancel, scols.UserAccountHuaweiOpenid,
		scols.UserAccountHuaweiUnionID, scols.UserAccountWechatOpenId, scols.UserAccountMiniAppOpenId}

	serr := s.Update(wheres, &updatedata, updateCols...)
	return serr
}

// FindList 查询列表数据
func (s *DbSvcUserAccount) FindList(wheres []*where.Condition, extra *where.Extra) ([]*sentity.UserAccount, uint, error) {

	var entityList []*sentity.UserAccount
	//传入的entityList必须要加 &取地址符号，切片本身并不是指针，向函数传递一个切片时，实际上是复制了该切片的结构体
	err := dbops.FindListNew(&dbops.FindListConfig{
		Conditions:     wheres,
		Db:             s.dbRead,
		Extra:          extra,
		NewEntityList:  &entityList,
		GetSoftDelData: false,
		// Fields:        []string{"ID"},
		// RelationList: []*dbops.RelationItem{},
	})
	if err != nil {
		return nil, 0, err //返回空切片，0，错误
	}

	//开始统计总数
	total, err := dbops.GetTotalWithDb(wheres, new(sentity.UserAccount), s.dbRead)
	if err != nil {
		return []*sentity.UserAccount{}, 0, err
	}

	return entityList, uint(total), nil
}

// Update 更新数据
func (s *DbSvcUserAccount) Update(wheres []*where.Condition, dtoUpdate *sentity.UserAccount, columnsCfg ...string) error {
	// dbops.UpdateWithDb(wheres, new(sentity.UserAccount), dtoUpdate, s.dbWrite, columnsCfg...)
	err := dbops.UpdateNew(&dbops.UpdateConfNew{
		Wheres:           wheres,
		NewEntity:        new(sentity.UserAccount),
		Db:               s.dbWrite,
		UpdateColumnsCfg: columnsCfg,
		DataUpdate:       dtoUpdate,
	})
	return err
}

// Delete 删除数据
func (s *DbSvcUserAccount) Delete(wheres []*where.Condition) error {
	err := dbops.DeleteNew(&dbops.DeleteConfig{
		Wheres:     wheres,
		Db:         s.dbWrite,
		SoftDelete: false,
		NewEntity:  new(sentity.UserAccount),
	})
	return err
}

// GetTotal 获取总数
func (s *DbSvcUserAccount) GetTotal(wheres []*where.Condition) (int64, error) {
	total, err := dbops.GetTotalWithDb(wheres, new(sentity.UserAccount), s.dbRead)
	return total, err
}

// ImportData 导入excel文件
func (s *DbSvcUserAccount) ImportData(filePath string, WhenErrorUpdate bool) (err error) {
	defer func() { //捕获异常
		if p := recover(); p != nil {
			err = fmt.Errorf("panic occurred: %v", p)
		}
	}()
	var data []sdto.UserAccountCreate
	result, err := myexcel.ParseExcel(filePath, &sdto.UserAccountCreate{})
	if err != nil {
		return err
	}
	//转成切片
	for _, item := range result {
		data = append(data, *item.(*sdto.UserAccountCreate))
	}

	//插入数据
	err = dbops.CreateBatch(data, new(sentity.UserAccount), WhenErrorUpdate, s.dbWrite)
	if err != nil {
		return err
	}

	return err
}

// ExportData  导出数据
func (s *DbSvcUserAccount) ExportData(params *dto.ReqSearch) (string, error) {
	total, err := s.GetTotal(params.Wheres)
	if err != nil {
		return "", err
	}
	if total > int64(params.Extra.PageSize) {
		return "", fmt.Errorf("导出总数%v大于%v,请分批导出", total, params.Extra.PageSize)
	}
	//开始构造数据并存入本地文件
	list, _, _ := s.FindList(params.Wheres, params.Extra)
	if list == nil || len(list) <= 0 {
		return "", fmt.Errorf("导出数据为空")
	}
	//开始写入数据
	filePath := "uploads/export/exportUserAccount_" + time.Now().Format("20060102150105") + ".xlsx"
	err = myexcel.GenStructListFile(list, &sdto.UserAccountInfo{}, filePath)
	if err != nil {
		return "", err
	}
	return filePath, nil
}
